home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dskut
/
qic02_11.zip
/
QIC02.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-28
|
31KB
|
1,084 lines
/* WARNING WARNING WARNING WARNING WARNING
*
* This is the MSDOS device driver code for Archive SC402 / SC499R
* QIC02 tape controllers.
*
* This code is BETA and is known to have:
*
* - BUGS (there *has* to be at least one :-)
* - code 'stolen' from H.H. Bergman's QIC02 device driver for
* Linux-386, Doug Braun's SCSI driver, TCDEV.ARC (from Simtel20)
* - lack of documentation
* - dirty code
*
* This code is dangerous, not only when running but also when looking
* at it: it is 100% HACKwork (TM) and the result of a hardware guy trying
* to write software. Perhaps it will work, perhaps not.
*
* NEVER use this code to do anything serious like dumping / restoring
* important data :-)
*
* History:
*
* 0.0 - initial 'working' version
* 0.1 - internal
* fixed the 'can only write slowly' bug:
* fixed read_status & dma_wait routine
* 0.2 - internal
* cleaned up code
* changed device name from TAPE to TAPE$
* removed printf's to reduce code size
* fixed some suspicious pointer conversions
* 0.3 - limited release
* removed alloc mem on 64K DMA wrap since it didn't work
* 0.4 - added info returned for mt status, e.g. error count
* 1.0 - ready for public release (at last...)
* 1.1 - no change to QIC02.C but needed to patch TCDEV.OBJ to already
* have the device driver attributes properly set in order to
* get things going with an OS/2 DOS box.
*
*
* Eddy Olk
* email: eddy@duteca.et.tudelft.nl
*
*
* Oh, almost forgot:
*
* QIC02 tape device driver for MSDOS
* Copyright (C) 1993 Eddy Olk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <dos.h>
#include <string.h>
#include <mem.h>
#include <ctype.h>
#include "mtio.h"
#include "qic02.h"
int errno; /* to keep the linker happy */
int iobase = 0x220; /* default IObase = 0x220h */
int dmanr = 3; /* default DMA channel = 3 */
int intnr = 7; /* default IRQ number = 7 */
/* (currently not used) */
#define DUMMY iobase+3 /* dummy I/O port for reading */
/* used to get some sort of CPU */
/* independant minimum time */
#define VERSION "1.1"
#define DEVICENAME "TAPE$ "
struct srh {
char len;
char unit;
char cmd;
int status;
char res[8];
union {
struct { /* init */
char units;
char far *kaddr;
char far *baddr;
} cin;
struct { /* media check */
char media, stat;
} cmc;
struct { /* build parameter block. */
char media;
char far *taddr;
char far *baddr;
} cbpb;
struct { /* reading and writing */
char media;
char far *taddr;
unsigned count;
unsigned start;
} crw;
struct { /* nondestructive read no wait */
char ch;
} cic;
} c;
};
extern char dev_name[9];
extern int dev_attr;
#ifdef USE_PRINTF
char msg[100];
#endif
char buffer[1024]; /* emergency buffer */
char far *abuf; /* non 64K crossing 512 byte emergency */
char far *buf;
char far *bufptr;
static char device_open;
static char bytes_transferred;
static char readmode;
static unsigned error_count;
static unsigned underrun_count;
static long fileno = 0;
static long blkno = 0;
static char move_dir = 1;
/* variables for tape status */
static unsigned char statusbyte[6];
/* variables for DMA stuff */
static char far *dptr;
static unsigned dlen;
static unsigned adlen;
static char rwflag;
static unsigned dma_residue;
biosputs(s)
char *s;
{
static char c;
static int oldbp;
while (*s) {
c = *s++;
if (c == '\n') {
oldbp = _BP;
_AL = '\r';
_AH = 0x0e;
_BH = 0;
geninterrupt(0x10);
_BP = oldbp;
}
oldbp = _BP;
_AL = c;
_AH = 0x0e;
_BH = 0;
geninterrupt(0x10);
_BP = oldbp;
}
}
/* Find out 14 possible exceptions, got these from the Archive docs */
int get_qicerror()
{
if (errstat(1,ST1)) {
if (errstat(1,PAR)) {
if (errstat(0,ST0) && errstat(0,UDE)) {
return THCerr; /* 14: Throughcheck error. FATAL on */
/* write, CONTINUABLE on read */
}
else {
return PARerr; /* 13: bus parity error. CONTINUABLE */
}
}
if (errstat(1,POR)) /* 11: Reset occured. FATAL */
return PORerr;
if (errstat(1,ILL)) /* 10: Illegal command. FATAL */
return ILLerr;
if (errstat(1,MBD)) {
if (errstat(0,ST0) && errstat(0,FIL))
return MARerr; /* 12: Marginal block. CONTINUABLE */
}
if (errstat(1,EOD)) {
if (errstat(0,ST0) && errstat(0,EOM)) {
return EDMerr; /* 8: End of data & EOM. CONTINUABLE */
}
else {
return EODerr; /* 7: End of data. CONTINUABLE */
}
}
}
if (errstat(0,ST0)) {
if (errstat(0,FIL))
return RFMerr; /* 9: Read file mark. CONTINUABLE */
if (errstat(0,UDE)) {
if (errstat(1,ST1) && errstat(1,BOM)) {
return RWAerr; /* 4: Read or write abort. FATAL */
}
else {
if (errstat(0,BNL)) {
return RFBerr; /* 6: Read error, filler block. */
/* CONTINUABLE */
}
else {
return RBBerr; /* 5: Read error, bad block. */
/* CONTINUABLE */
}
}
}
if (errstat(0,EOM))
return EOMerr; /* 3: End Of Media. CONTINUABLE */
if (errstat(0,CNI))
return CNIerr; /* 1: Cartridge not in place. FATAL */
if (errstat(0,WRP))
return WRPerr; /* 2: Write protected cartridge. FATAL */
}
return 0; /* 0: No errors? Hope we didn't miss one */
}
void wait_more_than_usec(int delay)
{
int i;
for (i=0; i<delay; i++) {
inportb(DUMMY);
inportb(DUMMY);
}
}
int read_status()
{
int i;
wait_stat; /* wait for ready or exception */
outdata(RDSTATUS); /* write read status command */
setreq; /* set request */
wait_rdy; /* wait for ready, ignore possible */
/* still active exception */
disable();
resetreq; /* reset request */
wait_nrdy; /* wait until ready is (has been) inactive */
enable();
while (!(inportb(STATUS) & DIRC)); /* wait for data direction change */
for (i=0; i<6; i++) {
wait_stat; /* wait for ready, don't hope for exceptions */
if (is_exception) {
return DEADerr; /* unexpected exception, tape drive */
/* must be dead */
}
statusbyte[i] = indata; /* get status byte [i] */
setre